#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "testlib.h"

static const char* _alf = "ABCEHIKLNOPRSTUWXYZ";

int pair_to_int(const char* s) {
    const char* p;
    int rz;

    p = _alf;
    rz = -1;
    while (*p != 0) {
        if (*p == *s) {
            rz = p - _alf;
            break;
        }
        ++p;
    }
    if (rz < 0) return rz;
    if (s[1] < '1' || s[1] > '9') return -1;
    rz *= 9;
    rz += (s[1] - '0' -1);
    //printf("rz=%d\n", rz);
    return rz;
}

// 170 is maximum value
unsigned short int_to_pair(int n) {
    int k = n / 9;
    int r = n % 9;
    if (k > 18) return 0xFFFF;  // error value
    return (_alf[k] << 8) | r + '1';
}

bool validate_id(const char* id) {
    int x, len;
    len = strlen(id);
    if ((len+1) % 3 > 0) return false;          // odd length
    if (len < 2 || len > 29) return false;      // too short or too long
    const char* iv = id;
    while (*iv != 0) {
        x = pair_to_int(iv);
        if (x < 0) {
            return false;
        }
        if (iv[2] != 0 && iv[2] != '-') return false;   // 
        iv += 3;
        if (iv > id + len) iv--;    // point to zero
    }
    return true;
}
int set_value(char *p, int val) {
    unsigned short w = int_to_pair(val);
    if (w == 0xFFFF) return 0;
    p[0] = HIBYTE(w);
    p[1] = LOBYTE(w);
    return 1;
}

char* get_next(const char* id) {
    char* p;
    int k;                  // id digit in numeric form
    bool do_ext = false;    // carry flag
    char* ret2;
    char* ret = (char*)calloc(strlen(id) + 1, 1);    // same length for calculation
    if (ret == NULL) return NULL;
    strcpy(ret, id);
    p = ret + strlen(id) - 2;   // id have at least 2 bytes

    while (p >= ret) {
        k = pair_to_int(p);
        ++k;
        if (k == 171) {         // carry
            set_value(p, 0);
            if (p == ret) do_ext = true;
            p -= 3;
        }
        else {  // transform back to pair and store it
            set_value(p, k);
            break;
        }
    }
    if (do_ext) {   // ...and len == 10 -> overflow
        // realloc, copy 'A1', concat with current id
        if (strlen(id) > 28) return NULL;      // overflow!
        ret2 = (char*)calloc(strlen(id) + 4,1);
        if (!ret2) return NULL; // alloc error!
        set_value(ret2, 0);
        ret2[2] = '-';
        strcat(ret2, ret);
        free(ret);
        return ret2;
    }
    return ret;
}
